/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds.object;

import net.worlds.WorldsException;
import net.worlds.Main;
import org.jbox2d.common.Vec2D;
import se.krka.kahlua.vm.JavaFunction;
import se.krka.kahlua.vm.LuaCallFrame;


public class Model extends GameObject{
    public boolean collideChildren = true;
    public class CollideChildrenFunction implements JavaFunction
    {
        public int call(LuaCallFrame callFrame, int nArguments) {
            if(nArguments != 2)
                throw new RuntimeException("setCollideChildren() requires 1 argument");
            if(!(callFrame.get(1) instanceof Boolean))
                throw new RuntimeException("setCollideChildren() requires a boolean argument");
            collideChildren = ((Boolean)callFrame.get(1));
            return 0;
        }
    }
    public Model(String type) throws WorldsException
    {
        super(type);
        addFunction("breakJoints", new JavaFunction()
        {

            public int call(LuaCallFrame callFrame, int nArguments) {
                Main.runInMainThread(new Runnable()
                {
                    public void run()
                    {
                        try {
                            breakJoints();
                        } catch (WorldsException ex) {
                            throw new RuntimeException(ex);
                        }
                    }
                });
                return 0;
            }

        });
        addFunction("makeJoints", new JavaFunction()
        {
            public int call(LuaCallFrame callFrame, int nArguments) {
                makeJoints();
                return 0;
            }
        });
        addFunction("setCollideChildren", new CollideChildrenFunction());
    }
    public Model() throws WorldsException
    {
        super("Model");
        addFunction("setCollideChildren", new CollideChildrenFunction());
        addFunction("breakJoints", new JavaFunction()
        {

            public int call(LuaCallFrame callFrame, int nArguments) {
                Main.runInMainThread(new Runnable()
                {
                    public void run()
                    {
                        try {
                            breakJoints();
                        } catch (WorldsException ex) {
                            throw new RuntimeException(ex);
                        }
                    }
                });
                return 0;
            }
        });
        addFunction("makeJoints", new JavaFunction()
        {
            public int call(LuaCallFrame callFrame, int nArguments) {
                makeJoints();
                return 0;
            }
        });
        addFunction("moveTo", new JavaFunction() {

            public int call(final LuaCallFrame callFrame, int nArguments) {
                if(nArguments != 3 || !(callFrame.get(1) instanceof Vec2D) || !(callFrame.get(2) instanceof Part))
                    throw new RuntimeException("moveTo() requires a Vec2D and a part");
                final Vec2D pos = (Vec2D) callFrame.get(1);
                final Part part = (Part) callFrame.get(2);
                Runnable r = new Runnable()
                {
                    public void run() {
                        moveTo(pos, part);
                    }
                };
                Main.runInMainThread(r);
                return 0;
            }
        });
        //x_;
    }
    public void moveTo(Vec2D position, Part reference)
    {
        Vec2D refPos = reference.getPosition();
        Vec2D diff = new Vec2D(position.x - refPos.x, position.y - refPos.y);
        synchronized(children)
        {
            for(GameObject c : children)
            {
                if(c instanceof Part)
                {
                    try {
                        Part p = (Part) c;
                        p.setPosition(p.getPosition().add(diff));
                    } catch (WorldsException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        }
    }
    public void makeJoints()
    {
        Runnable r = new Runnable()
        {
            public void run() {
                synchronized(children)
                {
                    for(GameObject c : children)
                    {
                        try {
                            if(c instanceof Part)
                                ((Part) c).makeJoints((Model) instance);
                            else if(c instanceof Model)
                                ((Model)c).makeJoints();
                        } catch (WorldsException ex) {
                            throw new RuntimeException(ex);
                        }
                    }
                }
            }
        };
        Main.runInMainThread(r);
    }
    public void clearJointDefs()
    {
        Runnable r = new Runnable()
        {
            public void run() {
                synchronized(children)
                {
                    for(GameObject c : children)
                    {
                        if(c instanceof Part)
                            ((Part) c).clearJointDefs();
                        else if(c instanceof Model)
                            ((Model)c).clearJointDefs();
                    }
                }
            }
        };
        Main.runInMainThread(r);
    }
    public void breakJoints() throws WorldsException
    {
        synchronized(children)
        {
            for(GameObject obj : children)
            {
                if(obj instanceof Part)
                    ((Part)obj).breakJoints();
                else if(obj instanceof Model)
                    ((Model)obj).breakJoints();
            }
        }
    }
    public void resetFiltering()
    {
        synchronized(children)
        {
            for(GameObject c : children)
            {
                if(c instanceof Part)
                    ((Part) c).getBody().resetFiltering();
                else if(c instanceof Model)
                    ((Model)c).resetFiltering();
            }
        }
    }
}
